package cn.bonoon.services;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.batatasframework.common.ParameterReader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.bonoon.core.plugins.AccountAssignService;
import cn.bonoon.entities.AccountEntity;
import cn.bonoon.entities.GroupAccountEntity;
import cn.bonoon.entities.GroupEntity;
import cn.bonoon.entities.GroupRoleEntity;
import cn.bonoon.entities.RoleAccountEntity;
import cn.bonoon.entities.RoleEntity;
import cn.bonoon.kernel.support.IOperator;
import cn.bonoon.kernel.support.models.ObjectCollection;
import cn.bonoon.kernel.support.models.ObjectItem;
import cn.bonoon.kernel.support.services.ServiceSupport;

@Service
@Transactional(readOnly = true)
public class AccountAssignServiceImpl extends ServiceSupport implements AccountAssignService{
	private final String _1 = "select x from RoleEntity x where x.status=1 and x.deleted=false";
	private final String _3 = "select x.role.id from RoleAccountEntity x where x.invalid=false and x.account.id=?";
	private final String _4 = "select x from RoleAccountEntity x where x.account.id=?";

	private List<RoleAccountEntity> _getRoleAssign(Long id) {
		return __list(RoleAccountEntity.class, _4, id);
	}
	
	@Override
	public List<ObjectItem> roles(AccountEntity account) {
		List<RoleEntity> roles = __list(RoleEntity.class, _1);
		List<Long> sids = __list(Long.class, _3, account.getId());
		return ObjectCollection.valueOf(roles, sids);
	}
	
	@Override
	public Object rolesByAccount(Long id) {
		String ql = "select x.role from RoleAccountEntity x where x.invalid=false and x.account.id=?";
		return __list(RoleEntity.class, ql, id);
	}
	
	@Override
	public List<ObjectItem> roles(GroupEntity group) {
		List<RoleEntity> roles = __list(RoleEntity.class, _1);
		String ql = "select x.role.id from GroupRoleEntity x where x.invalid=false and x.group.id=?";
		List<Long> sids = __list(Long.class, ql, group.getId());
		return ObjectCollection.valueOf(roles, sids);
	}
	
	private static final int DEFAULT_PAGE_SIZE = 50;
	
	@Override
	public void saveGroupRoles(IOperator opt, Long id, Long... roleIds) {
		/*
		 * 用户级关联的角色发生了改变，那么该用户组下的所有用户都应该被标示为需要进行“菜单刷新”
		 * 
		 */
		String ql = "select x from GroupRoleEntity x where x.group.id=?";
		List<GroupRoleEntity> oldRoles = __list(GroupRoleEntity.class, ql, id);
//		List<Long> sids = Arrays.asList(roleIds);
		
		for(GroupRoleEntity oldRole : oldRoles){
			Long needCheckOldRoleid = oldRole.getRole().getId();
			oldRole.setInvalid(true);
			for(int i = 0; i < roleIds.length; i++){
				if(needCheckOldRoleid.equals(roleIds[i])){
					roleIds[i] = null;
					oldRole.setInvalid(false);
					break;
				}
			}
//			oldRole.setInvalid(!sids.remove(oldRole.getRole().getId()));
			entityManager.merge(oldRole);
		}

//		if(!sids.isEmpty()){
			Date now = new Date();
			GroupEntity group = entityManager.find(GroupEntity.class, id);
			for(Long rid : roleIds){
				if(null == rid) continue;
				GroupRoleEntity newRole = new GroupRoleEntity();
				newRole.setGroup(group);
				newRole.setCreateAt(now);
				newRole.setCreatorId(opt.getId());
				newRole.setRole(entityManager.find(RoleEntity.class, rid));
				entityManager.persist(newRole);
			}
	}

	@Override
	@Transactional
	public void saveAccountRoles(IOperator opt, Long aid, Long... roleIds) {
		/*
		 * 一个用户的角色发生了变化，需要进行刷新
		 */
		List<RoleAccountEntity> oldRoles = _getRoleAssign(aid);
		//List<Long> sids = Arrays.asList(roleIds);
		
		for(RoleAccountEntity oldRole : oldRoles){
			Long needCheckOldRoleid = oldRole.getRole().getId();
			oldRole.setInvalid(true);
			for(int i = 0; i < roleIds.length; i++){
				if(needCheckOldRoleid.equals(roleIds[i])){
					roleIds[i] = null;
					oldRole.setInvalid(false);
					break;
				}
			}
			entityManager.merge(oldRole);
		}
		
//		if(!sids.isEmpty()){
		Date now = new Date();
		AccountEntity account = entityManager.find(AccountEntity.class, aid);
		for(Long rid : roleIds){
			if(null == rid) continue;
			RoleAccountEntity newRole = new RoleAccountEntity();
			newRole.setAccount(account);
			newRole.setCreateAt(now);
			newRole.setCreatorId(opt.getId());
			newRole.setRole(entityManager.find(RoleEntity.class, rid));
			entityManager.persist(newRole);
		}
//		}
	}

	@Override
	@Transactional
	public void saveRoleGroups(IOperator user, Long id, Long... ids) {
		/*
		 * 某一个角色所关联的用户组发生了变化，则需要通知所有用户组下的用户
		 */
		String ql = "select x from GroupRoleEntity x where x.role.id=?";
		List<GroupRoleEntity> oldGroups = __list(GroupRoleEntity.class, ql, id);
//		List<Long> sids = Arrays.asList(ids);

		for(GroupRoleEntity oldGroup : oldGroups){
			Long needCheckOldGroupid = oldGroup.getGroup().getId();
			oldGroup.setInvalid(true);
			for(int i = 0; i < ids.length; i++){
				if(needCheckOldGroupid.equals(ids[i])){
					ids[i] = null;
					oldGroup.setInvalid(false);
					break;
				}
			}
//			oldGroup.setInvalid(!sids.remove(oldGroup.getGroup().getId()));
			entityManager.merge(oldGroup);
		}

//		if(!sids.isEmpty()){
			Date now = new Date();
			RoleEntity role = entityManager.find(RoleEntity.class, id);
			for(Long gid : ids){
				if(null == gid) continue;
				GroupRoleEntity newGroup = new GroupRoleEntity();
				newGroup.setRole(role);
				newGroup.setCreateAt(now);
				newGroup.setCreatorId(user.getId());
				newGroup.setGroup(entityManager.find(GroupEntity.class, gid));
				entityManager.persist(newGroup);
			}
//		}
	}
	
	@Override
	@Transactional
	public void saveAccountGroups(IOperator user, Long id, Long... ids) {
		/*
		 * 一个用户所在的用户组发生了变化，也需要刷新菜单
		 */
		String ql = "select x from GroupAccountEntity x where x.account.id=?";
		List<GroupAccountEntity> oldGroups = __list(GroupAccountEntity.class, ql, id);
		//List<Long> sids = Arrays.asList(ids);
		
		for(GroupAccountEntity oldGroup : oldGroups){
			Long needCheckOldGrouid = oldGroup.getGroup().getId();
			oldGroup.setInvalid(true);
			for(int i = 0; i < ids.length; i++){
				if(needCheckOldGrouid.equals(ids[i])){
					ids[i] = null;
					oldGroup.setInvalid(false);
					break;
				}
			}
//			oldGroup.setInvalid(!sids.remove(oldGroup.getGroup().getId()));
			entityManager.merge(oldGroup);
		}
		
//		if(!sids.isEmpty()){
		Date now = new Date();
		AccountEntity account = entityManager.find(AccountEntity.class, id);
		for(Long gid : ids){
			if(gid == null) continue;
			GroupAccountEntity newGroup = new GroupAccountEntity();
			newGroup.setAccount(account);
			newGroup.setCreateAt(now);
			newGroup.setCreatorId(user.getId());
			newGroup.setGroup(entityManager.find(GroupEntity.class, gid));
			entityManager.persist(newGroup);
		}
//		}
	}

	private List<GroupEntity> internalGroups(){
		String ql = "select x from GroupEntity x where x.deleted=false and x.status=1";
		return __list(GroupEntity.class, ql);
	}

	@Override
	public List<ObjectItem> groups(AccountEntity account) {
		String ql = "select x.group.id from GroupAccountEntity x where x.invalid=false and x.account.id=?";
		return ObjectCollection.valueOf(internalGroups(), __list(Long.class, ql, account.getId()));
	}
	
	@Override
	public List<GroupEntity> groupsByAccount(Long id) {
		String ql = "select x.group from GroupAccountEntity x where x.invalid=false and x.account.id=?";
		return __list(GroupEntity.class, ql, id);
	}
	
	@Override
	public List<ObjectItem> groups(RoleEntity role) {
		String ql = "select x.group.id from GroupRoleEntity x where x.invalid=false and x.role.id=?";
		return ObjectCollection.valueOf(internalGroups(), __list(Long.class, ql, role.getId()));
	}

	@Override
	public List<GroupAccountEntity> accounts(GroupEntity group, int pageIndex) {
		String ql = "select x from GroupAccountEntity x where x.invalid=false and x.group.id=?";
		return __query(GroupAccountEntity.class, ql, group.getId())
				.setFirstResult(pageIndex * DEFAULT_PAGE_SIZE)
				.setMaxResults(DEFAULT_PAGE_SIZE)
				.getResultList();
	}
	
	@Override
	public List<RoleAccountEntity> accounts(RoleEntity role, int pageIndex) {
		String ql = "select x from RoleAccountEntity x where x.invalid=false and x.role.id=?";
		return __query(RoleAccountEntity.class, ql, role.getId())
				.setFirstResult(pageIndex * DEFAULT_PAGE_SIZE)
				.setMaxResults(DEFAULT_PAGE_SIZE)
				.getResultList();
	}
	
	@Override
	public List<RoleAccountEntity> searchRoleAccounts(ParameterReader parameter) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<GroupAccountEntity> searchGroupAccounts(
			ParameterReader parameter) {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * 角色上的用户和用户组上的用户可能会比较多，所以不能直接使用全部列出来的管理方式；
	 * 而是需要能分页进行处理
	 */
	
	@Override
	public List<RoleAccountEntity> deleteRoleAccounts(ParameterReader parameter) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<GroupAccountEntity> deleteGroupAccounts(
			ParameterReader parameter) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<RoleAccountEntity> saveRoleAccounts(ParameterReader parameter) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<GroupAccountEntity> saveGroupAccounts(ParameterReader parameter) {
		// TODO Auto-generated method stub
		return null;
	}

}
